#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>

const std::string HttpSep = "\r\n";
const std::string wwwroot = "./wwwroot";
const std::string homepage = "index.html";

class HttpRequest
{
public:
    HttpRequest() : _req_blank(HttpSep), _path(wwwroot)
    {
    }

    ~HttpRequest() {}

    bool Getline(std::string &request, std::string *line)
    {
        auto pos = request.find(HttpSep);
        if (pos == std::string::npos)
            return false;
        *line = request.substr(0, pos);
        request.erase(0, pos + HttpSep.size());
        return true;
    }

    void Deserialize(std::string &request) // 将浏览器发送到服务器的请求进行反序列化
    {
        std::string line;
        if (!Getline(request, &line))
            return;
        _req_line = line;

        while (true)
        {
            bool ok = Getline(request, &line);
            if (ok && line.empty())
            {
                _req_content = request;
                break;
            }
            else if (ok && !line.empty())
            {
                _req_header.push_back(line);
            }
            else
                break;
        }
        return;
    }

    void DebugHttp()
    {
        std::cout << "_req_line: " << _req_line << std::endl;
        for (auto &line : _req_header)
        {
            std::cout << "----> " << line << std::endl;
        }
        std::cout << "_req_blank: " << _req_blank << std::endl;
        std::cout << "_req_content: " << _req_content << std::endl;
    }

    void PraseReqline() // 将_req_line中的内容按照空格提取出来
    {
        std::stringstream ss(_req_line);
        ss >> _method >> _url >> _http_version;

        if (_url == "/") // "./wwwroot/index.html"
        {
            _path += _url;
            _path += homepage;
        }
        else
        {
            _path += _url;
        }
    }

    void PraseSuffix() // 得到_path文件路径的文件后缀
    {
        auto pos = _path.rfind(".");
        if (pos == std::string::npos)
            _suffix = ".html";
        else
            _suffix = _path.substr(pos);
    }

    void Parse()
    {
        PraseReqline();

        PraseSuffix();
    }

    std::string GetFileContentHelper(const std::string &path)
    {
        std::ifstream in(path, std::ios::binary);
        if (!in.is_open())
            return "";
        in.seekg(0, in.end);
        int filesize = in.tellg();
        in.seekg(0, in.beg);

        std::string content;
        content.resize(filesize);
        in.read((char *)content.c_str(), filesize);

        in.close();

        return content;
    }

    std::string GetFileContent()
    {
        return GetFileContentHelper(_path);
    }

    std::string Get_404()
    {
        return GetFileContentHelper("./wwwroot/404.html");
    }

    std::string GetSuffix()
    {
        return _suffix;
    }

private:
    std::string _req_line;
    std::vector<std::string> _req_header;
    std::string _req_blank;
    std::string _req_content;

    // 请求行 [方法] [路径] [协议版本]
    std::string _method;
    std::string _url;
    std::string _http_version;

    std::string _path;   // 资源的路径
    std::string _suffix; // 请求资源后缀
};

const std::string BlankSep = " ";
const std::string LineSep = "\r\n";

class HttpResponse
{
public:
    HttpResponse() : _http_version("HTTP/1.0"), _status_code(200), _status_code_desc("OK"), _resp_blank(LineSep)
    {
    }
    ~HttpResponse() {}

    void MakeStatusLine()
    {
        _status_line = _http_version + BlankSep + std::to_string(_status_code) + BlankSep + _status_code_desc + LineSep;
    }

    void SetStatusCode(int code)
    {
        _status_code = code;
    }

    void SetStatusCodeDesc(const std::string &statuscodedesc)
    {
        _status_code_desc = statuscodedesc;
    }

    void AddResqHeader(const std::string &resqheader)
    {
        _resp_header.push_back(resqheader);
    }

    void AddContent(const std::string &content)
    {
        _resp_content = content;
    }

    std::string Serialize() // 将响应进行序列化返回给客户端
    {
        std::string response_str = _status_line;
        for (const auto &header : _resp_header)
            response_str += header;
        response_str += _resp_blank;
        response_str += _resp_content;
        return response_str;
    }

private:
    std::string _status_line;
    std::vector<std::string> _resp_header;
    std::string _resp_blank;
    std::string _resp_content;

    // 响应行 [协议版本] [状态码] [状态码描述]
    std::string _http_version;
    int _status_code;
    std::string _status_code_desc;
};